home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
135_01
/
calc.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
10KB
|
496 lines
/*
calc.c---very long integer calculator in reverse polish
notational form. It is to some small extent programable,
in that you may write a string to any one of 10 arrays
which I've called scripts. These are executed by way of
the command 'exe' which requires a single numeric operand
as a prefix. You might think of this as a simple version
of a HP11c handheld with a very large LCD display! I suppose
this program should have a manual, but since I only intended
it to be a demo for vli.crl and math.crl, I didn't bother
and now...well like topsy, it sort of grew out of hand.
I hope that if you are interested, the code should be clear enough to
explain all. It also should be easy to extend...some things
I had thought to add were better (less dangerous!) recursion, and
maybe the ability to read/write a set of scripts from/to a
text file. Then later, conditionals based on boolean evaluation
of top-of-stack...jumps and script calls. Then it could be
extended to allow rational numbers, complex too for that matter.
After a while, it might evolve into a small language. Who knows!
by Hugh S. Myers
build:
n>cc calc
n>clink calc vli math cio
3/20/84
4/9/84
commands:
'|' print '\n' (allows embedded newlines in
scripts for display)
^Z clearscreen on Televideo terminals (see CRT
note below)
'=' print top of stack (tos)
'clr' clear stack
'pop' next on stack (nos) becomes tos
'xch' swap tos and nos
'clt' set tos to zero
op 'pgm' do a getline and place result in script[op]
op 'exe' retrieve script[op] and execute it as
though it were from the terminal
1 'sho' display number stack on screen
2 'sho' display variable list on screen
3 'sho' display script list on screen
op1 op2 'sto' store op2 to variable[op1]
op 'rcl' push variable[op] on tos
op 'fac' push factorial(op) on tos
op 'sqrt' push square-root(op) on tos
op 'neg' || '~' push negative(op) on tos
op 'sqr' push square(op) on tos
op 'abs' push absolute-value(op) on tos
op1 op2 'add' || '+' tos = op1 + op2
op1 op2 'sub' || '-' tos = op1 - op2
op1 op2 'mul' || '*' tos = op1 * op2
op1 op2 'div' || '/' tos = op1 / op2
op1 op2 'pow' || '^' tos = op1 ** op2
op1 op2 'mod' || '#' tos = remainder op1 / op2
op1 op2 'min' tos = minimum op1, op2
op1 op2 'max' tos = maximum op1, op2
CRT notes...
This was developed on a TVI 950...so if you have one (or
an emulation) fine. If not change the defines for TVI950
and CLEARSCREEN...
*/
#include <bdscio.h>
#define TVI950 1 /* terminal type for specific flashy stuff */
/* use #undef for vanilla version */
#define MAX 256 /* number of columns of string arrays */
#define DEPTH 10 /* number of rows of string arrays */
#define SETIO 0x12 /* for cio.crl */
#define ESC 27
#define CLEARSCREEN 26
#define CR 13
#define BS 8
#define DEL 127
#define LIMIT 20 /* nesting level allowed for script recursion */
#define streq(s1,s2) !strcmp(s1,s2) /* reverse the logic for clarity */
/*
globals
*/
char script[DEPTH][MAX];
char stack[DEPTH][MAX];
char number[MAX];
char var[DEPTH][MAX];
char line[MAX], keyword[MAX];
int i, lastch, errnumb, deep;
char flagged;
main()
{
int j;
for(j=0;j<DEPTH;j++)
strcpy(var[j],"0");
i = 0; /* stack pointer */
strcpy(stack[i],"empty stack");
strcpy(number,"");
strcpy(keyword,"");
ttymode(SETIO);
flagged = FALSE;
puts("c calculator\n");
prompt();
forever {
parse(getchar());
if(deep)
deep = 0;
}
}
parse(ch)
char ch;
{
char xscript[MAX], temp[MAX];
int l, n, key;
forever {
if(ch == '\n' || ch == CR || ch == '|') {
putchar('\n');
prompt();
return OK;
}
if(ch == CLEARSCREEN) {
putchar(ch);
prompt();
return OK;
}
if(ch < ' ' || ch > '~')
return OK;
else
putchar(ch);
if(isdigit(ch)) {
sstrcat(number,ch);
return OK;
}
if(!isspace(ch)) {
sstrcat(keyword,ch);
return OK;
}
if(!isnull(number)) {
pushnumber();
return OK;
}
else {
if(isnull(keyword)) /* allows repeat spaces */
return OK;
key = isop(keyword);
strcpy(keyword,"");
if(!key) {
calcerror(3);
return FAIL;
}
switch(key) {
case 1: /* '=' sign */
rprintf(stack[i]);
putchar(' ');
return OK;
case 8: /* "clr" */
i=0;
return OK;
}
if(i<1) {
calcerror(1);
return FAIL;
}
switch(key) {
case 2: /* "pgm" */
i--;
n=atoi(stack[i+1]);
if(n<0 || n>9) {
calcerror(5);
return FAIL;
}
getline(script[n],MAX);
prompt();
return OK;
case 3: /* "exe" */
i--;
deep++;
if(deep > LIMIT) {
calcerror(4);
return FAIL;
}
n=atoi(stack[i+1]);
if(n<0 || n>9) {
calcerror(5);
return FAIL;
}
strcpy(xscript,script[n]);
for(l=0;l<strlen(xscript);l++)
parse(xscript[l]);
return OK;
case 4: /* "pop" */
i--;
return OK;
case 5: /* "fac" or '!' */
strcpy(stack[i],facl(stack[i]));
return OK;
case 6: /* "sqrt" */
strcpy(stack[i],sqrtl(stack[i]));
return OK;
case 23: /* "sqr" */
strcpy(stack[i],mull(stack[i],stack[i]));
return OK;
case 7: /* "neg" or '~' */
strcpy(stack[i],smull(stack[i],-1));
return OK;
case 9: /* "clt" */
strcpy(stack[i],"0");
return OK;
case 10: /* "abs" */
strcpy(stack[i],absl(stack[i]));
return OK;
case 11: /* "rcl" */
n=atoi(stack[i]);
if(n<0 || n>9) {
calcerror(5);
i--;
return FAIL;
}
strcpy(stack[i],var[n]);
return OK;
case 12: /* "sho" */
i--;
n=atoi(stack[i+1]);
if(n<0 || n>3) {
calcerror(5);
return FAIL;
}
switch(n) {
case 1: /* show number stack */
if(i == 0) {
rprintf(stack[i]);
putchar(' ');
return OK;
}
putchar('\n');
for(l=i;l>0;l--) {
sprintf(line,"s(%d) %s",l,stack[l]);
rprintf(line);
putchar('\n');
}
break;
case 2: /* show variable list */
putchar('\n');
for(l=0;l<DEPTH;l++) {
sprintf(line,"v(%d) %s",l,var[l]);
rprintf(line);
putchar('\n');
}
break;
case 3: /* show program list */
putchar('\n');
for(l=0;l<DEPTH;l++) {
sprintf(line,"p(%d) %s",l,script[l]);
rprintf(line);
putchar('\n');
}
break;
}
prompt();
return OK;
}
if(i<2) {
calcerror(2);
return FAIL;
}
switch(key) {
case 13: /* "pow" or '^' */
strcpy(stack[i-1],powl(stack[i-1],stack[i]));
break;
case 14: /* "add" or '+' */
strcpy(stack[i-1],addl(stack[i-1],stack[i]));
break;
case 15: /* "sub" or '-' */
strcpy(stack[i-1],subl(stack[i-1],stack[i]));
break;
case 16: /* "mul" or '*' */
strcpy(stack[i-1],mull(stack[i-1],stack[i]));
break;
case 17: /* "div" or '/' */
strcpy(stack[i-1],divl(stack[i-1],stack[i]));
break;
case 18: /* "mod" or '#' */
strcpy(stack[i-1],modl(stack[i-1],stack[i]));
break;
case 19: /* "min" */
strcpy(stack[i-1],minl(stack[i-1],stack[i]));
break;
case 20: /* "max" */
strcpy(stack[i-1],maxl(stack[i-1],stack[i]));
break;
case 21: /* "sto" */
n=atoi(stack[i-1]);
if(n<0 || n>9) {
calcerror(5);
i-=2;
return FAIL;
}
strcpy(var[n],stack[i]);
i--;
break;
case 22: /* "xch" */
strcpy(temp,stack[i-1]);
strcpy(stack[i-1],stack[i]);
strcpy(stack[i],temp);
return OK;
}
i--;
return OK;
}
}
}
isop(s)
char *s;
{
/*
no operands required at this level.
*/
if(iseq(s,"equ") || iseq(s,"="))
return 1;
/*
beyond here there must be at least one operand, ie.; i must be > 0.
*/